package com.yixun.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.ThreadPoolExecutor;

@Configuration
public class AsyncPoolConfig {

    /**
     * 配置线程池
     * @return
     *  int i = Runtime.getRuntime().availableProcessors();//获取到服务器的cpu内核
     *         executor.setCorePoolSize(5);//核心池大小
     *         executor.setMaxPoolSize(100);//最大线程数
     *         executor.setQueueCapacity(1000);//队列程度
     *         executor.setKeepAliveSeconds(1000);//线程空闲时间
     *         executor.setThreadNamePrefix("tsak-asyn");//线程前缀名称
     *         拒绝策略
     *
     * rejectedExectutionHandler参数字段用于配置绝策略，常用拒绝策略如下
     * AbortPolicy：用于被拒绝任务的处理程序，它将抛出RejectedExecutionException
     * CallerRunsPolicy：用于被拒绝任务的处理程序，它直接在execute方法的调用线程中运行被拒绝的任务。
     * DiscardOldestPolicy：用于被拒绝任务的处理程序，它放弃最旧的未处理请求，然后重试execute。
     * DiscardPolicy：用于被拒绝任务的处理程序，默认情况下它将丢弃被拒绝的任务。
     */

    //分析下继承关系：
    //
    // 1、ThreadPoolTaskExecutor extends (2)ExecutorConfigurationSupport
    //	implements (3)AsyncListenableTaskExecutor, (4)SchedulingTaskExecutor
    //2、 ExecutorConfigurationSupport extends CustomizableThreadFactory implements BeanNameAware, InitializingBean, DisposableBean
    //
    //3、public interface AsyncListenableTaskExecutor extends AsyncTaskExecutor
    //4、public interface SchedulingTaskExecutor extends AsyncTaskExecutor
    //
    //从上继承关系可知：
    //ThreadPoolExecutor是一个java类不提供spring生命周期和参数装配。
    //ThreadPoolTaskExecutor实现了InitializingBean, DisposableBean ，xxaware等，具有spring特性
    //
    //AsyncListenableTaskExecutor提供了监听任务方法(相当于添加一个任务监听，提交任务完成都会回调该方法)
    //
    //简单理解：
    //1、ThreadPoolTaskExecutor使用ThreadPoolExecutor并增强，扩展了更多特性
    //2、ThreadPoolTaskExecutor只关注自己增强的部分，任务执行还是ThreadPoolExecutor处理。
    //3、前者spring自己用着爽，后者离开spring我们用ThreadPoolExecutor爽。
    //注意：ThreadPoolTaskExecutor 不会自动创建ThreadPoolExecutor需要手动调initialize才会创建
    //    如果@Bean 就不需手动，会自动InitializingBean的afterPropertiesSet来调initialize
    @Bean(name = "asyncPool")
    public ThreadPoolTaskExecutor getAsyncThreadPoolTaskExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setCorePoolSize(200);//核心池大小  //核心线程数
        taskExecutor.setMaxPoolSize(800);//最大线程数
        taskExecutor.setQueueCapacity(500);//队列程度  //任务队列的大小
        taskExecutor.setKeepAliveSeconds(200);//线程空闲时间
        taskExecutor.setThreadNamePrefix("yx-");//线程前缀名称
        //用于被拒绝任务的处理程序，它直接在execute方法的调用线程中运行被拒绝的任务。
        // 线程池对拒绝任务（无线程可用）的处理策略，目前只支持AbortPolicy、CallerRunsPolicy；默认为后者
        taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        taskExecutor.initialize();
        return taskExecutor;
    }
    //高并发下核心线程数要这么设置的呀
    //要看情况的，要是IO密集还是CPU密集，大概是CPU密集设置为跟核心数一样大小，IO密集型设置为2倍CPU核心数
    //处理流程
    //1.查看核心线程池是否已满，不满就创建一条线程执行任务，否则执行第二步。
    //
    //2.查看任务队列是否已满，不满就将任务存储在任务队列中，否则执行第三步。
    //
    //3.查看线程池是否已满，即就是是否达到最大线程池数，不满就创建一条线程执行任务，否则就按照策略处理无法执行的任务
}
